/**
 * copyright 2007, hi5 networks 
 *
 * Implements the opensocial.Container apis.
 * @constructor
 */
 opensocial.Hi5Container = function() {
  opensocial.Container.call(this);
};
opensocial.Hi5Container.inherits(opensocial.Container);

/**
 * Initialize the container with the specified state.
 *
 * @param {Person} viewer Person object that corresponds to the viewer.
 * @param {Person} opt_owner Person object that corresponds to the owner.
 * @param {Collection&lt;Person&gt;} opt_viewerFriends A collection of the
 *    viewer's friends
 * @param {Collection&lt;Person&gt;} opt_ownerFriends A collection of the
 *    owner's friends
 * @param {{Map&lt;String, String&gt;} opt_globalAppData map from key to value
 *    of the global app data
 * @param {{Map&lt;String, String&gt;} opt_instanceAppData map from key to value
 *    of this gadget's instance data
 * @param {Map&lt;Person, Map&lt;String, String&gt;&gt;} opt_personAppData map
 *    from person to a map of app data key value pairs.
 * @param {Array&lt;Activity&gt;} opt_activities An array of activity objects.
 */
 opensocial.Hi5Container.prototype.init = function(viewer,
                                               opt_owner,
                                               opt_viewerFriends,
                                               opt_ownerFriends,
                                               opt_globalAppData,
                                               opt_instanceAppData,
                                               opt_personAppData,
                                               opt_activities) {
  this.viewer = viewer;
  this.owner = opt_owner;
  this.viewerFriends = opt_viewerFriends || {};
  this.ownerFriends = opt_ownerFriends || {};
  this.globalAppData = opt_globalAppData || {};
  this.instanceAppData = opt_instanceAppData || {};
  this.personAppData = opt_personAppData || {};
  this.activities = opt_activities || {};
};

opensocial.Hi5Container.Mode = {CANVAS:"canvas", PROFILE:"profile", PREVIEW:"preview"};

opensocial.Hi5Container.prototype.navigateTo = function(mode, params) {

    switch(mode) {
      case opensocial.Hi5Container.Mode.CANVAS :
          window.location.href = "http://" + document.location.host + "/friend/displayAppCanvas.do?appName=Songs+iLike"
          break;
      case opensocial.Hi5Container.Mode.PROFILE :
          break;
      case opensocial.Hi5Container.Mode.PREVIEW :
          break;
    };
};

opensocial.Hi5Container.prototype.urlTo = function(mode, params) {
    var url;
    switch(mode) {
      case opensocial.Hi5Container.Mode.CANVAS :
          // TODO hack, fix for general case
          url = "/friend/displayAppCanvas.do?appName=Songs+iLike";
          alert(params);
          alert(params.length);
          break;
      case opensocial.Hi5Container.Mode.PROFILE :
          break;
      case opensocial.Hi5Container.Mode.PREVIEW :
          break;
    };
    return url;
};

/**
 * Deprecated.
 */
opensocial.Hi5Container.prototype.requestInstallApp = function(appUrl, opt_onSuccess, opt_onFailure) {
	// TODO implement
	opt_onSuccess();
};

/**
 * Deprecated.
 */
opensocial.Hi5Container.prototype.requestUninstallApp = function(appUrl, opt_onSuccess, opt_onFailure) {
	// TODO implement
	opt_onSuccess();
};

/**
 * Make the specified person as friend by moving them from the nonFriends
 * list to the friends list.
 *
 * @param {String} id The id associated with the person to be made a friend.
 * @param {Function} opt_onSuccess The callback method on successful completion.
 * @param {Function} opt_onFailure The callback method on failure.
 */
opensocial.Hi5Container.prototype.requestMakePersonAFriend = function(id, opt_onSuccess, opt_onFailure) {
  // Find if this id is in the list of non friends list
  var found = null;
  this.nonFriends.each(function(contact) {
    if(contact.getId() == id) {
      found = contact;
      this.nonFriends.removeAt(contact.getId());
    }
  });
  if(found == null) {
    opt_onFailure();
    return; // person not found in non friend list
  }

  // Make this person a friend by moving to friends collection and
  // deleting from non friend list
  this.friends.putAt(found.id, found);

  opt_onSuccess();
};

/**
 * Make the specified person as nonfriend by moving them from the friends
 * list to the nonFriends list.
 *
 * @param {String} id The id associated with the person to be removed
 * as a friend.
 * @param {Function} opt_onSuccess The callback method on successful completion.
 * @param {Function} opt_onFailure The callback method on failure.
 */
opensocial.Hi5Container.prototype.requestMakePersonNotAFriend = function(id,
    opt_onSuccess, opt_onFailure) {

  // Find if this person is actually a friend
  var found = null;
  this.friends.each(function(contact) {
    if(contact.getId() == id) {
      found = contact;
      this.friends.removeAt(contact.getId());
    }
  });
  if(found == null) {
    opt_onFailure();
    return; // person not found in friend list
  }

  // Add this person to non-friend list
  this.nonFriends.putAt(found.id, found);
  opt_onSuccess();
};


/**
 * This method returns the data requested about the viewer and his/her friends.
 * Since this is an in memory container, it is merely returning the member
 * variables. In a real world container, this would involve making an ajax
 * request to fetch the values from the server.
 *
 * To keep this simple (for now), the PeopleRequestFields values such as sort
 * order, filter, pagination, etc. specified in the DataRequest are ignored and
 * all requested data is returned in a single call back.
 *
 * @param {Object} dataRequest The object that specifies the data requested.
 * @param {Function} callback The callback method on completion.
 */
opensocial.Hi5Container.prototype.requestData = function(dataRequest, callback) {
  var requestObjects = dataRequest.getRequestObjects();
  var dataResponseValues = {};
  
  	// decrement this as we complete each request
	var numLeft = requestObjects.length;
	
	// This gets called when each request finishes
	var reqFinished = function(requestName, requestedValue) {
        dataResponseValues[requestName] = new opensocial.ResponseItem(request,requestedValue);

		numLeft--;
		if (numLeft == 0) {
		  callback(new opensocial.DataResponse(dataResponseValues));	
		}
	}
	
	// cycle through each element
  for (var i = 0; i < requestObjects.length; i++) {
	
    var request = requestObjects[i].request;
    var requestName = requestObjects[i].key;

    var requestedValue;

    switch(request.type) {
      case opensocial.DataRequest.RequestType.FETCH_PERSON :
        var personId = request.parameters.id;
        if (personId == opensocial.DataRequest.PersonId.VIEWER) {
          requestedValue = this.viewer;
        } else if (personId == opensocial.DataRequest.PersonId.OWNER) {
          requestedValue = this.owner;
        } else {
          // See if the person is listed in an existing friends list
          if (requestedValue == null && this.viewerFriends != null) {
          	requestedValue = this.viewerFriends.get(personId)
          }
          if (requestedValue == null && this.ownerFriends != null) {
	        requestedValue = this.ownerFriends.get(personId);
          }
          if (requestedValue == null) {
          	// If we get here then the data is not locally cached, reach out and fetch it
	
			jQuery.getJSON("http://api.hi5.com/json/profile/foaf/" + personId + "?callback=?", function(data){
				person = data["rdf.RDF"]["foaf.Person"];
				requestedValue = new people.Hi5Person(personId, {name: person["foaf.givenName"], picture:person["foaf.img"]["@resource"]}, false, false);
				reqFinished(requestName, requestedValue);
			});
          }
        }
        
        if (requestedValue != null)
        	reqFinished(requestName, requestedValue);
        
        break;

      case opensocial.DataRequest.RequestType.FETCH_FRIENDS :
        // TODO(doll): Support more than just the 2 friend groups
        var groupId = request.parameters.idSpec;
        
        var uid = null;
        if (groupId == opensocial.DataRequest.Group.VIEWER_FRIENDS) {
	      uid = this.viewer.getId();
        } else if (groupId == opensocial.DataRequest.Group.OWNER_FRIENDS) {
	      uid = this.owner.getId();
        } else {
	      // TODO unknown what we do here...
              reqFinished(requestName, requestedValue);
        }

	    // If we found a valid id fetch it
        if (uid != null) {          
              jQuery.getJSON("http://api.hi5.com/json/profile/foaf/" + uid + "?callback=?", function(data){
          		knows = data["rdf.RDF"]["foaf.Person"]["foaf.knows"];
				var friends = new s2.data.Repository('Friends', 'Friend');
				var fidx = 0;
				
				if (knows != null) {
					jQuery.each(knows, function () {
						person = this["foaf.Person"];
						if (person != null)
                                                        // <rdfs:seeAlso resource="http://api.hi5.com/rest/foaf/159987912"/>
							var id = person["foaf.mbox_sha1sum"];
                                                        seeAlso = person["rdfs.seeAlso"]["@resource"];

                                                        if (seeAlso) {
                                                           // ugh, hack the uid off the end
                                                           id = seeAlso.substring(seeAlso.lastIndexOf('/')+1);
                                                        }
                                                           
							friends.putAt(fidx++, new opensocial.Hi5Person(id, 
			   					{name: person["foaf.givenName"],
			    				 picture: person["foaf.img"]["@resource"]}, false, false));
   					});
				}
   				reqFinished(requestName, friends);
          });
        }  
        break;

      case opensocial.DataRequest.RequestType.FETCH_PEOPLE :
        //TODO: Need to fill in the value for list of persons
        break;

      case opensocial.DataRequest.RequestType.FETCH_GLOBAL_DATA :
        // TODO(doll): Filter by key
        requestedValue = this.globalAppData;
        reqFinished(requestName, requestedValue);
        
        break;

      case opensocial.DataRequest.RequestType.FETCH_INSTANCE_DATA :
        // TODO(doll): Filter by key
        requestedValue = this.instanceAppData;
        reqFinished(requestName, requestedValue);        
        break;

      case opensocial.DataRequest.RequestType.UPDATE_INSTANCE_DATA :
        this.instanceAppData[request.parameters.key] = request.parameters.value;
        reqFinished(requestName, requestedValue);
        
        break;

      case opensocial.DataRequest.RequestType.FETCH_PERSON_DATA :
        // TODO(doll): Filter by person and key
        requestedValue = this.personAppData;
        reqFinished(requestName, requestedValue);
        
        break;

      case opensocial.DataRequest.RequestType.UPDATE_PERSON_DATA :
        if (this.personAppData[request.parameters.id] == null) {
          this.personAppData[request.parameters.id] = {};
        }
        this.personAppData[request.parameters.id][request.parameters.key]
            = request.parameters.value;
        reqFinished(requestName, requestedValue);
            
        break;

      case opensocial.DataRequest.RequestType.FETCH_ACTIVITIES :
        // TODO(doll): Respect all the other activity parameters
        requestedValue = this.activities;

        reqFinished(requestName, requestedValue);
        
        break;
    }
  } // end of for loop
};

